# -*- coding:utf-8 -*-
import os,sys
import re
import traceback
import time
from collections import deque
sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__)), os.pardir, os.pardir))
import supeanut_config
sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__)), os.pardir))
from CommonLib.mylog import mylog
from ExrightsTool import ExrightsTool
from CommonLib.StockTool import StockTool

'''
作者：supeanut
创建时间：2016-xx-xx xx:xx:xx
功能描述：
	xxx
	xxxxx
相关配置：
	supeanut_config.XXX
历史改动：
	2016-xx-xx: xxxxxx
'''
class KlineRecog:
	def __init__(self):
		# K线实体长度定义(单日开收盘波动绝对值),闭开区间
		self.XingK_entityLen = [0.0, 0.005]
		self.xiaoK_entityLen = [0.005, 0.025]
		self.zhongK_entityLen = [0.025, 0.045]
		self.daK_entityLen = [0.045, 99.99]
	
	# 参数合理范围，[[min,max],step]
	# 区别整数为step数值
	def getParamRange(self, func_name):
		if func_name in ["hongSanBing","sanWuYa"]:
			return {'item_len':[[2,5],1],'xiaoK_entityMin':[[0.001,0.007],0.003],\
				    'xiaoK_entityMax':[[0.025,0.035],0.005],'yingXianPercent':[[0.6,1.5],0.3]}
		if func_name == "yinBaoYang":
			return {'yinPCR':[[0.5,0.5],0.1],'yangPCR':[[0.7,0.7],0.1]}
			

	# 红三兵
	# item_len：红N兵， xiaoK_entityLen：小阳线实体长度， yingXianPercent：影线最大占实体比例
	def hongSanBing(self, itemList, item_len=3, xiaoK_entityMin=0.005, xiaoK_entityMax=0.025, yingXianPercent=0.618, period=[None,None]):
		if len(itemList) < item_len:
			return []
		period_start = itemList[0][0] if period[0] is None else period[0]
		period_end = itemList[-1][0] if period[1] is None else period[1]
		# 初始化待识别的items组
		temp_items = deque([])
		temp_items_date = ""
		for i in range(0, item_len-1):
			# [open,close,high,low]
			temp_items.append(itemList[i][1:5])
		# 全量识别
		result_list = []
		for item in itemList[item_len-1:]:
			temp_items_date = item[0]
			temp_items.append(item[1:5])
			# 识别算法
			reg_tag = True
			pre_close = -99.99
			pre_open = 999999.99
			item_index = 0
			for temp_item in temp_items:
				item_index += 1
				oc_wave = (temp_item[1] - temp_item[0]) / temp_item[0]
				# 阴线出局
				if oc_wave < 0.0:
					reg_tag = False
					break
				# 非小阳线出局
				oc_wave_abs = abs(oc_wave)
				if oc_wave_abs < xiaoK_entityMin or oc_wave_abs >= xiaoK_entityMax:
					reg_tag = False
					break
				# 影线过长出局
				if (temp_item[2] - temp_item[1]) > yingXianPercent * (temp_item[1] - temp_item[0]):
					reg_tag = False
					break
				if (temp_item[0] - temp_item[3]) > yingXianPercent * (temp_item[1] - temp_item[0]):
					reg_tag = False
					break
				# close小于pre_close出局
				if temp_item[1] < pre_close:
					reg_tag = False
					break
				# open不在昨日实体内，出局(第一根K线无视此条件)
				if item_index > 1 and (temp_item[0] > pre_close or temp_item[0] < pre_open):
					reg_tag = False
					break
				pre_close = temp_item[1]
				pre_open = temp_item[0]
			# 识别结果
			if reg_tag is True:
				# period鉴别
				if temp_items_date >= period_start and temp_items_date <= period_end:
					result_list.append(temp_items_date)
			temp_items.popleft()
		return result_list
	
	# 三乌鸦，参考红三兵
	def sanWuYa(self, itemList, item_len=3, xiaoK_entityMin=0.005, xiaoK_entityMax=0.025, yingXianPercent=0.618, period=[None,None]):
		if len(itemList) < item_len:
			return []
		period_start = itemList[0][0] if period[0] is None else period[0]
		period_end = itemList[-1][0] if period[1] is None else period[1]
		# 初始化待识别的items组
		temp_items = deque([])
		temp_items_date = ""
		for i in range(0, item_len-1):
			# [open,close,high,low]
			temp_items.append(itemList[i][1:5])
		# 全量识别
		result_list = []
		for item in itemList[item_len-1:]:
			temp_items_date = item[0]
			temp_items.append(item[1:5])
			# 识别算法
			reg_tag = True
			pre_close = 999999.99
			pre_open = 999999.99
			item_index = 0
			for temp_item in temp_items:
				item_index += 1
				oc_wave = (temp_item[1] - temp_item[0]) / temp_item[0]
				# 阳线出局
				if oc_wave > 0.0:
					reg_tag = False
					break
				# 非小阴线出局
				oc_wave_abs = abs(oc_wave)
				if oc_wave_abs < xiaoK_entityMin or oc_wave_abs >= xiaoK_entityMax:
					reg_tag = False
					break
				# 影线过长出局
				if (temp_item[2] - temp_item[0]) > yingXianPercent * (temp_item[0] - temp_item[1]):
					reg_tag = False
					break
				if (temp_item[1] - temp_item[3]) > yingXianPercent * (temp_item[0] - temp_item[1]):
					reg_tag = False
					break
				# close大于等于pre_close出局
				if temp_item[1] >= pre_close:
					reg_tag = False
					break
				# open不在昨日实体内，出局(第一根K线无视此条件)
				if item_index > 1 and (temp_item[0] > pre_open or temp_item[0] < pre_close):
					reg_tag = False
					break
				pre_close = temp_item[1]
				pre_open = temp_item[0]
			# 识别结果
			if reg_tag is True:
				if temp_items_date >= period_start and temp_items_date <= period_end:
					result_list.append(temp_items_date)
			temp_items.popleft()
		return result_list

	# 长阳包长阴
	# yinPCR: 需要大于阴线实体长度，yangPCR：需要大于阳线实体长度
	def yinBaoYang(self, itemList, yinPCR, yangPCR, period=[None,None]):
		# 小于2个周期的实例，直接返回空
		if len(itemList) < 2:
			return []
		# 在意的回测区间
		period_start = itemList[0][0] if period[0] is None else period[0]
		period_end = itemList[-1][0] if period[1] is None else period[1]
		# 开始算法
		datetime_list = []
		pre_item = itemList[0]
		for item in itemList[1:]:
			# 判断长阴长度
			pre_open = pre_item[1]
			pre_close = pre_item[2]
			if pre_open <> 0:
				PCR = (pre_close - pre_open) / pre_open
			else:
				pre_item = item
				continue
			if PCR > -yinPCR:
				pre_item = item
				continue
			# 判断阳线长度
			cur_open = item[1]
			cur_close = item[2]
			if cur_open <> 0:
				PCR = (cur_close - cur_open) / cur_open
			else:
				pre_item = item
				continue
			if PCR < yangPCR:
				pre_item = item
				continue
			# 判断包住
			if cur_open > pre_close or cur_close < pre_open:
				pre_item = item
				continue
			# 判断是否处于回测区间
			cur_datetime = item[0]
			if cur_datetime >= period_start and cur_datetime <= period_end:
				datetime_list.append(cur_datetime)
			pre_item = item
		return datetime_list


if __name__ == '__main__':
	obj = ExrightsTool()
	stock_obj = StockTool()
	obj2 = KlineRecog()
	flag, itemList = obj.getAdjItemList("300033", "pre", "day")
	#print obj2.hongSanBing(itemList, 3, 0.0, 0.025, 1.8)
	#print obj2.sanWuYa(itemList, 3, 0.0, 0.025, 1.0)
	print obj2.yinBaoYang(itemList, 0.05, 0.06)
